package edu.gmu.projects.fireresponder.environment;


import java.text.DecimalFormat;

import edu.gmu.projects.util.geo.CoordinateCalculator;

public class Location implements Comparable<Location> {

	private double latitude;
	private double longitude;
	
	// used for hashcode and equals, so hash functions will consider anything 
	// within 6 decimal places of accuracy to be the same place 
	private String latStr;
	private String longStr;
	private DecimalFormat decimalFormatter;

	public Location()
	{
		decimalFormatter = new DecimalFormat("0.000000");
	}
	
	public Location(double latitude, double longitude) {
		decimalFormatter = new DecimalFormat("0.000000");

		setLatitude(latitude);
		setLongitude(longitude);
	}
	
	public Location(String location) {
		decimalFormatter = new DecimalFormat("0.000000");

		String[] vals = location.split("[,\\s]+");
		
		setLatitude(Double.parseDouble(vals[0].trim()));
		setLongitude(Double.parseDouble(vals[1].trim()));
	}
	
	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
		latStr = decimalFormatter.format(latitude);
	}

	public double getLongitude() {
		return longitude;
	}

	public void setLongitude(double longitude) {
		this.longitude = longitude;
		longStr = decimalFormatter.format(longitude);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((latStr == null) ? 0 : latStr.hashCode());
		result = prime * result + ((longStr == null) ? 0 : longStr.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Location other = (Location) obj;
		if (latStr == null) {
			if (other.latStr != null)
				return false;
		} else if (!latStr.equals(other.latStr))
			return false;
		if (longStr == null) {
			if (other.longStr != null)
				return false;
		} else if (!longStr.equals(other.longStr))
			return false;
		return true;
	}

	public String toString() {
		return latStr + ", " + longStr;
	}

	public double distanceInKm(Location location) {
		return CoordinateCalculator.getDistance(this, location);
	}
	
	public double distanceInKm(double lat, double lng) {
		return CoordinateCalculator.getDistance(this, new Location(lat, lng));
	}
	
	public static void main(String[] args) {
		System.out.println(new Location("45, 32").toString());
 		System.out.println(new Location("45  32").toString());
		System.out.println(new Location("45,32").toString());
		System.out.println(new Location("45 32").toString());
		System.out.println(new Location("45,  , 32").toString());
		System.out.println(new Location("45, 32 5").toString());		

		Location a = new Location(38.87899, -77.21425);
		Location b = new Location(38.87685, -77.21275);
		Location c = new Location(38.87866, -77.20767);
		Location d = new Location(38.87843, -77.20719);
		
		System.out.println(a.compareTo(b));
		System.out.println(a.compareTo(c));
		System.out.println(a.compareTo(d));

		System.out.println(b.compareTo(a));
		System.out.println(b.compareTo(c));
		System.out.println(b.compareTo(d));
	
		System.out.println(c.compareTo(a));
		System.out.println(c.compareTo(b));
		System.out.println(c.compareTo(d));

		System.out.println(d.compareTo(a));
		System.out.println(d.compareTo(b));
		System.out.println(d.compareTo(c));

		System.out.println(a.compareTo(a));
	}

	@Override
	public int compareTo(Location l) {
		if (this.latitude == l.latitude && this.longitude == l.longitude)
			return 0;
	
		if (this.longitude < l.longitude) {
			return -1;
		} else if (this.longitude > l.longitude) {
			return 1;
		} else { // longitudes are equal
			if (this.latitude < l.latitude) {
				return -1;
			} else { // equals already done
				return 1;
			}
		}
	}
}